import React, { Component } from 'react';
// import Module from '../wasm/libffmpeg'
import WebGLPlayer from '../webgl'

export class Video extends Component {
  static objRef = 0;
  static displayName = Video.name;
  constructor(props) {
    super(props);
    this.video=React.createRef();
    this.canvas = React.createRef();
    this.state={file:"",height:window.innerHeight,type:"online"};

    this.image_data = [];
    this.videoWidth = 0;
    this.videoHeight = 0;
    this.player = {};
    this.websock = {};
    this.callback = 0;
    this.objref = ++Video.objRef;

    this.handle = undefined;
    this.buf = undefined;
  }
  initRealTimeSetting(){
    this.player = new WebGLPlayer(this.canvas.current, {preserveDrawingBuffer: false});
    this.websock = new WebSocket( 'ws://' + window.location.host + '/ws'+this.objref);
    this.websock.binaryType = "arraybuffer";
    this.websock.onmessage=this.recv_data.bind(this);
  }
  componentDidMount(){
    if(this.state.type==="online"){
      this.initRealTimeSetting();
      this.display();
    }
    else{
      this.websock.close();
      this.websock={};
      this.player={};
    }
  }
  endDecode(){
    window.Module._EndDecode(this.handle);
    window.Module._free(this.handle);
    window.Module._free(this.buf);
    this.handle = undefined;
    this.buf = undefined;
  }
  async recv_data(evt){
    let bitData = new Uint8Array(evt.data);
    if(bitData[0]===0xcc&&bitData[1]===0xff&&bitData[2]===0xaa&&bitData[3]===0xff){
      if(bitData[4]===1){ 
        this.videoWidth = (bitData[12]&0xff)|((bitData[13]&0xff)<<8)|((bitData[14]&0xff)<<16)|((bitData[15]&0xff)<<24);
        this.videoHeight = (bitData[16]&0xff)|((bitData[17]&0xff)<<8)|((bitData[18]&0xff)<<16)|((bitData[19]&0xff)<<24);
        if(window.isLoadWasm && this.handle!==undefined){
          this.endDecode();
        }
      }
      else if(bitData[4]===2){
        if(window.isLoadWasm){
          if(this.handle===undefined){
            this.buf = window.Module._malloc(3/2*this.videoWidth*this.videoHeight);//yuv420数据
            this.handle = window.Module._BeginDecode(this.buf,27,window.callback);
          }
          let data = bitData.subarray(12);
          window.Module.HEAP8.set(data,this.buf);
          window.Module._ImageDecode(this.handle,this.buf,data.length);
        }
      }
    }
    this.websock.send(new Uint8Array(1));//发送心跳数据
  }
  async display(){
    requestAnimationFrame(this.display.bind(this));

    if(Object.getOwnPropertyNames(this.player).length===0){
      this.image_data = []
      return;
    }
    if(this.image_data.length>1){
      let data = this.image_data[0];
      this.player.renderFrame(data.y,data.ylen,data.u,data.ulen,
        data.v,data.vlen,data.w,data.h);
      this.image_data.shift();
    }
  }
  settype(type){
    let oldState = this.state.type;
    this.setState({type:type},()=>{
      if(type!==oldState){
        if(type!=='online'){
          if(window.isLoadWasm && this.handle!==undefined){
            this.websock.close();
            this.websock={};
            this.player={};
            //end decoder
            this.endDecode();
          }
        }
        else{
          this.initRealTimeSetting();
        }
      }
    });
  }
  setfile(file){
    this.setState({file:"video/getfile?file="+file});
  }
  render () {
    return (
      this.state.type==="online"?
      (
        <div style={{background:'#212529'}}>
          <canvas ref={this.canvas} style={{width:'100%',height:this.state.height*0.6}} />
        </div>
      ):(
        <div style={{objectFit:'contain'}}>
          <video ref={this.video} src={this.state.file} 
            style={{width:'100%',height:this.state.height*0.6}} 
            controls="controls" autoPlay="autoPlay" 
          >
            This is fallback text to display if the browser does not support the video element.
          </video>
        </div>
      )
    );
  }
}
